convert geo to Format class. (#998)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Fri, 27 Jan 2023 13:48:04 +0000 (06:48 -0700)
committerGitHub <noreply@github.com>
Fri, 27 Jan 2023 13:48:04 +0000 (06:48 -0700)
This also adds the encoding attribute to the xml declaration.
This also starts the loc element at the beginning of a line.
Previously we jumped through some hoops to avoid the above two
changes so we could exaclty match the original reference file.

We also pass the writer to the waypt_disp_all callback via a lambda.
This allows the output File and QXmlStreamWriter to be local which
simplified cleanup.

CMakeLists.txt
geo.cc
geo.h [new file with mode: 0644]
reference/gl.loc
vecs.cc

index d65981698fbaf676f06c7f59b68b97c9e4b6c8b6..ea6100cc3efb99b0b9dd9bbe2d7adb4be6a240b8 100644 (file)
@@ -223,6 +223,7 @@ set(HEADERS
   geocache.h
   geojson.h
   globalsat_sport.h
+  geo.h
   gpx.h
   grtcirc.h
   gtrnctr.h
diff --git a/geo.cc b/geo.cc
index 4144cf036f3d1be0d1287b743f850333929b7a43..37dd6c627020b04ef3a88fc25fb4a2e111dacbd1 100644 (file)
--- a/geo.cc
+++ b/geo.cc
 
  */
 
+#include "geo.h"
+
 #include <QByteArray>            // for QByteArray
 #include <QIODevice>             // for QIODevice
 #include <QString>               // for QString, operator==, QStringView::to...
 #include <QStringView>           // for QStringView
-#include <QVector>               // for QVector
 #include <QXmlStreamAttributes>  // for QXmlStreamAttributes
-#include <QXmlStreamReader>      // for QXmlStreamReader
-#include <QXmlStreamWriter>      // for QXmlStreamWriter, QXmlStreamReader::...
 #include <QtCore>                // for qPrintable, QIODeviceBase::ReadOnly
 
 #include "defs.h"
-#include "gbfile.h"              // for gbfclose, gbfopen, gbfputs, gbfile
 #include "geocache.h"            // for Geocache, Geocache::container_t, Geo...
 #include "src/core/file.h"       // for File
 
 
-static char* deficon = nullptr;
-static char* nuke_placer;
-static gbfile* ofd;
-static QString ostring;
-static QXmlStreamWriter writer(&ostring);
-
-static
-QVector<arglist_t> geo_args = {
-  {"deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr },
-  {"nuke_placer", &nuke_placer, "Omit Placer name", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr },
-};
-
 #define MYNAME "geo"
 
-// This really should be class-local...
-static QXmlStreamReader reader;
-static QString geo_read_fname;
-
-static Geocache::container_t wpt_container(const QString&);
-
-static void GeoReadLoc()
+void GeoFormat::GeoReadLoc(QXmlStreamReader& reader) const
 {
   Waypoint* wpt = nullptr;
   QString current_tag;
@@ -104,30 +84,33 @@ static void GeoReadLoc()
   }
 }
 
-static void
-geo_rd_init(const QString& fname)
+void GeoFormat::rd_init(const QString& fname)
+{
+  geo_fname = fname;
+}
+
+void GeoFormat::rd_deinit()
 {
-  geo_read_fname = fname;
+  geo_fname.clear();
 }
 
-static void
-geo_read()
+void GeoFormat::read()
 {
-  gpsbabel::File file(geo_read_fname);
-  file.open(QIODevice::ReadOnly);
-  reader.setDevice(&file);
+  gpsbabel::File ifile = gpsbabel::File(geo_fname);
+  ifile.open(QIODevice::ReadOnly);
+  QXmlStreamReader reader = QXmlStreamReader(&ifile);
 
-  GeoReadLoc();
+  GeoReadLoc(reader);
   if (reader.hasError())  {
     fatal(MYNAME ":Read error: %s (%s, line %ld, col %ld)\n",
           qPrintable(reader.errorString()),
-          qPrintable(file.fileName()),
+          qPrintable(ifile.fileName()),
           (long) reader.lineNumber(),
           (long) reader.columnNumber());
   }
 }
 
-Geocache::container_t wpt_container(const QString& args)
+Geocache::container_t GeoFormat::wpt_container(const QString& args)
 {
   Geocache::container_t v;
 
@@ -160,33 +143,17 @@ Geocache::container_t wpt_container(const QString& args)
   return v;
 }
 
-static void
-geo_rd_deinit()
-{
-}
-
-static void
-geo_wr_init(const QString& fname)
+void GeoFormat::wr_init(const QString& fname)
 {
-  ofd = gbfopen(fname, "w", MYNAME);
-
-  //writer.setAutoFormatting(true);
-  writer.setAutoFormattingIndent(0);
-  writer.writeStartDocument();
-
+  geo_fname = fname;
 }
 
-static void
-geo_wr_deinit()
+void GeoFormat::wr_deinit()
 {
-  writer.writeEndDocument();
-  gbfputs(ostring,ofd);
-  gbfclose(ofd);
-  ofd = nullptr;
+  geo_fname.clear();
 }
 
-static void
-geo_waypt_pr(const Waypoint* waypointp)
+void GeoFormat::geo_waypt_pr(const Waypoint* waypointp, QXmlStreamWriter& writer)
 {
   writer.writeStartElement(QStringLiteral("waypoint"));
 
@@ -252,29 +219,22 @@ geo_waypt_pr(const Waypoint* waypointp)
   writer.writeEndElement();
 }
 
-static void
-geo_write()
+void GeoFormat::write()
 {
+  gpsbabel::File ofile = gpsbabel::File(geo_fname);
+  ofile.open(QIODevice::WriteOnly | QIODevice::Text);
+  QXmlStreamWriter writer = QXmlStreamWriter(&ofile);
+
+  writer.setAutoFormatting(true);
+  writer.setAutoFormattingIndent(0);
+  writer.writeStartDocument();
   writer.writeStartElement(QStringLiteral("loc"));
   writer.writeAttribute(QStringLiteral("version"), QStringLiteral("1.0"));
-  // TODO: This could be moved to wr_init, but the pre GPX version put the two
-  // lines above this, so mimic that behaviour exactly.
-  writer.setAutoFormatting(true);
   writer.writeAttribute(QStringLiteral("src"), QStringLiteral("EasyGPS"));
-  waypt_disp_all(geo_waypt_pr);
-  writer.writeEndElement();
+  auto geo_waypt_pr_lambda = [this, &writer](const Waypoint* waypointp)->void {
+    geo_waypt_pr(waypointp, writer);
+  };
+  waypt_disp_all(geo_waypt_pr_lambda);
+  writer.writeEndElement(); // loc
+  writer.writeEndDocument();
 }
-
-ff_vecs_t geo_vecs = {
-  ff_type_file,
-  { (ff_cap)(ff_cap_read | ff_cap_write), ff_cap_none, ff_cap_none },
-  geo_rd_init,
-  geo_wr_init,
-  geo_rd_deinit,
-  geo_wr_deinit,
-  geo_read,
-  geo_write,
-  nullptr,
-  &geo_args,
-  NULL_POS_OPS
-};
diff --git a/geo.h b/geo.h
new file mode 100644 (file)
index 0000000..8545c6c
--- /dev/null
+++ b/geo.h
@@ -0,0 +1,76 @@
+/*
+    Copyright (C) 2002 Robert Lipe, robertlipe+source@gpsbabel.org
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+ */
+#ifndef GEO_H_INCLUDED_
+#define GEO_H_INCLUDED_
+
+#include <QString>           // for QString
+#include <QVector>           // for QVector
+#include <QXmlStreamReader>  // for QXmlStreamReader
+#include <QXmlStreamWriter>  // for QXmlStreamWriter
+
+#include "defs.h"
+#include "format.h"          // for Format
+#include "geocache.h"        // for Geocache, Geocache::container_t
+
+
+class GeoFormat : public Format
+{
+public:
+  QVector<arglist_t>* get_args() override
+  {
+    return &geo_args;
+  }
+
+  ff_type get_type() const override
+  {
+    return ff_type_file;
+  }
+
+  QVector<ff_cap> get_cap() const override
+  {
+    return { (ff_cap)(ff_cap_read | ff_cap_write), ff_cap_none, ff_cap_none };
+  }
+
+  void rd_init(const QString& fname) override;
+  void read() override;
+  void rd_deinit() override;
+  void wr_init(const QString& fname) override;
+  void write() override;
+  void wr_deinit() override;
+
+private:
+
+  /* Member Functions */
+
+  void GeoReadLoc(QXmlStreamReader& reader) const;
+  void geo_waypt_pr(const Waypoint*, QXmlStreamWriter& writer);
+  static Geocache::container_t wpt_container(const QString&);
+
+  /* Data Members */
+
+  char* deficon = nullptr;
+  char* nuke_placer{};
+  QString geo_fname;
+
+  QVector<arglist_t> geo_args = {
+    {"deficon", &deficon, "Default icon name", nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr },
+    {"nuke_placer", &nuke_placer, "Omit Placer name", nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr },
+  };
+};
+#endif // GEO_H_INCLUDED_
index 192d169f2dc16b4e7b7d2232723969a3eccfb5e0..724a8b7ec5f424ab4a31bd4afa3b6085f05e2dc3 100644 (file)
@@ -1,4 +1,5 @@
-<?xml version="1.0"?><loc version="1.0" src="EasyGPS">
+<?xml version="1.0" encoding="UTF-8"?>
+<loc version="1.0" src="EasyGPS">
 <waypoint>
 <name id="GCEBB"><![CDATA[Mountain Bike Heaven by susy1313]]></name>
 <coord lat="35.972033" lon="-87.134700"/>
diff --git a/vecs.cc b/vecs.cc
index e49c7ba7badd515f2de85f8e3c923f994391f47a..1007d331505e3d61b9d0ed13378b340786915412 100644 (file)
--- a/vecs.cc
+++ b/vecs.cc
@@ -47,6 +47,7 @@
 #include "gdb.h"               // for GdbFormat
 #include "geojson.h"           // for GeoJsonFormat
 #include "globalsat_sport.h"   // for GlobalsatSportFormat
+#include "geo.h"               // for GeoFormat
 #include "gpx.h"               // for GpxFormat
 #include "gtrnctr.h"           // for GtrnctrFormat
 #include "html.h"              // for HtmlFormat
@@ -115,7 +116,7 @@ struct Vecs::Impl {
 #if CSVFMTS_ENABLED
   XcsvFormat xcsv_fmt;
 #endif // CSVFMTS_ENABLED
-  LegacyFormat geo_fmt {geo_vecs};
+  GeoFormat geo_fmt;
   GpxFormat gpx_fmt;
   LegacyFormat garmin_fmt {garmin_vecs};
   GdbFormat gdb_fmt;